#pragma once
#include <QList>
#include <QObject>
#include <QActionGroup>
#include "dynamic_common_global.h"

class Model;
class QAction;
class QGLWidget;

/// @brief Default Rendering Class (bounding box)
/// 
/// @internal there is a specific reason for which the constructor is dummy and most
///           of the work is done in setup(). In this way we can instatiate a renderer
///           even if we don't have a rendering context.
class DYNAMIC_COMMON_EXPORT ModelRenderer : public QObject{
    Q_OBJECT

    /// @{ core plugin overload
    public:    
        /// @brief basic constructor
        /// => create your render modes
        ModelRenderer();
        /// @brief sets-up the rendering plugin, overload this method to
        /// => connect your renderer modes
        virtual void setup(Model* model, QGLWidget* widget, QAction* shader=NULL);
        
        /// @brief in this method the initialization of the renderer is performed. You only
        /// need to overload this if you have in mind of using high-performance rendering. 
        /// This would be the place where you perfom OpenGL buffers initialization
        /// @note when overloading, first call ModelRenderer::init()
        virtual void init(){ Q_ASSERT(isSetup()); }
        /// @brief overload this method to perform the rendering
        /// @note when overloading, first call ModelRenderer::render() so that 
        ///       pre-defined rendermodes can still work correctly
        virtual void render();
    /// @}
    
    /// @{ rendermodes
    protected:
        QActionGroup*   _modes;     ///< RENDER MODES
        QAction*        _mode_bbox; ///< DEFAULT BOUNDING BOX ACTION
    public:
        QActionGroup* renderModes(){ return _modes; }
        /// Changes the rendermode to the one specified by the string
        /// @param the string of the desired menu entry
        /// @returns true if the desired render mode was found
        bool setRenderMode(QString name);
    /// @}
        
    /// @{ internal status
    private:
        Model*          _model;   ///< (NULL) model we are rendering
        QGLWidget*      _widget;  ///< (NULL) widget we are rendering on
        QAction*        _shader;  ///< (NULL) action corresponding to used shader
    /// @}
                      
    /// @{ status verifier
    private:
        bool _isSetup; ///< (FALSE)
        bool _isInit;  ///< (FALSE)
    public:
        bool isSetup(){ return _isSetup; } ///< @brief has setup been called?
        bool isInit(){ return _isInit; } ///< @brief has init been called?
    /// @}
        
    /// @{ getters
    public:
        Model* model(){ Q_ASSERT(_isSetup); return _model; }
        QGLWidget* widget(){ Q_ASSERT(_isSetup); return _widget; }
        QAction* shader(){ Q_ASSERT(_isSetup); return _shader; }
    /// @}
};
